//#include "udp_includes.h"
//
#include<sched.h>
//
//#include "includes.h"
//#include "udpd/udp_includes.h"
#include "includes.h"
#include "udpd/udp_includes.h"

extern int fdtest;

//hmlee - SIGIO interrupt handler
void sig_handler_fasync(int signo, siginfo_t *si, void *data)
{
	hw10ms_int_handler(SIGUSR2);
	dbgCV(141) printf("%x\n",GetFpgaValue(12));
}


//hmlee - SIGALM interrupt handler
void sig_handler_alarm(int sig)
{
	//char err = mprotect((void*)mem, page_size,PROT_READ|PROT_WRITE);
	console_recover();
}


//hmlee - SIGINT interrupt handler
//void sig_handler_int(int dummy)
void sig_handler_int(int signo, struct siginfo *si,void *p)
{
	
}


//hmlee - SIGINT,SIGKILL,SIGTERM interrupt handler
void sig_handler_exit(int sig)
{
	exit(-1);
}


//hmlee - clean up mess before exit program
void atexit_handler(void)
{
struct timeval cur;
struct timeval bf;
int i;
//hmlee - need this to call SetFPGAProgHigh()
int fd = fdFPGA;

	if(child_calling_exit){return;}
	
	//hmlee - in case of waiting "Hit first key to stop auto start..." then ctrl+c 
	console_recover();
	
	//hmlee - dirty way to send counter module we are dead
	//SendIamDead();
	//SendMyStatus();
	
	backup_copy_log();
				
	//hmlee - sig off, not working!!!!!
	SetMeFail();
	
	//hmlee - ALL RED LEDs, otherwise it may look like "time-locked"
	LEDonResetOperation();
	DisplayLEDgpndu();
	
	gettimeofday(&bf, NULL);
	for(i=0;i<200;i++){
		gettimeofday(&cur, NULL);
		if(((cur.tv_sec*1000000 + cur.tv_usec) - 
			(bf.tv_sec*1000000 + bf.tv_usec)) > 1000000)
		{
			break;
		}
		usleep(100000);
	}


	SetFPGAProgHigh();
	
	usleep(20000);
	
	SetFPGAProgLow();
	SetFPGAProgHigh();
	usleep(80000);
	
	if(fdFPGA>0) {close(fdFPGA);}
	if(fdEB>0) {close(fdEB);}
	if(fdEB2>0) {close(fdEB2);}
	if(fdTOD>0) {close(fdTOD);}
	if(fdRbSRO>0) {close(fdRbSRO);}
//	if(fdDUAL>0) {close(fdDUAL);}
//	if(fdRLOG>0) {close(fdRLOG);}
	
	close_udpd();
	//hmlee - disable beep, otherwise beep will not go off
	
	//hmlee - close que0, que2
	//hmlee - maybe not..take a look at the /proc/sysvipc/msg to see what happen if not..
	//if(IPC.msgQid0 != -1) {msgctl(IPC.msgQid0, IPC_RMID, 0);}
	
	//hmlee - notify couter-GRCA we are dead
	munlockall();
	
	printf("GRCA exit\n");
}


//hmlee - to see something from telnet or ssh, we do fifo
int redirect_printf_to_fifo(char* path)
{
	int result;
	
	result = mkfifo(path, 0777);
	
	if(( result == -1) && (errno != EEXIST)){
		printf("error creating fifo, %d, %s\n", errno, strerror(errno));
		return -1;
	}
	
	int fdFIFO = open(path, O_RDWR|O_NONBLOCK);

	//redirect stdout and stderr to fifo
	dup2(fdFIFO, STDOUT_FILENO);
	dup2(fdFIFO, STDERR_FILENO);
	
	close(fdFIFO);
	
	return 1;
}

int debug_test_run = 0;
void ResetFPGA(int fd)
{
	SetFPGAProgHigh();

	msleep(20);

	SetFPGAProgLow();
	SetFPGAProgHigh();
	msleep(80);
}
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main( int argc, char **argv )
{
struct sigaction sa;
struct itimerval timer;
int flags;
unsigned char debug_fpga_off=0;
int argcount;
struct sched_param schedp;

struct sigaction act;


	for(argcount = 1; argcount<argc; argcount++){
		if(!strcmp(argv[argcount], "-f")){debug_fpga_off=1;}
		if(!strcmp(argv[argcount], "-t")){debug_test_run=1;}
	}
	
	if(debug_fpga_off){printf("---> NO FPGA CONFIGURATION !!!\n");}
	if(debug_test_run){printf("---> DEBUG TEST RUN !!!\n");}
	
	Init_LOG();
	
	//hmlee - register function being called at exit
	if(atexit(atexit_handler)){
		printf("cannot set exit function\n");
        exit(-1);
	}
	
        
	//hmlee - put console back to canonical mode
	console_recover();

	//Open FPGA Driver ----------------------------------------------------
	printf("Open FPGA Driver\n");

	fdFPGA = open( DRIVER_NODE, O_RDWR | O_NONBLOCK );

	printf( "###Open:%s,fd:%d\n", DRIVER_NODE, fdFPGA);
	//fdFPGA = open( DRIVER_NODE, O_RDWR );
	if ( fdFPGA < 0 )
	{
		printf( "Open Error ...:%s\n", DRIVER_NODE);
		exit(-1);
	}
	//--------------------------------------------------------------
	//init fpga ----------------------------------------------------
	//ResetFPGA(fdFPGA);
	//if(!abortboot(ABORT_BOOT_DELEY) && !debug_fpga_off){
	if(!debug_fpga_off){
		fpga_init(fdFPGA);
	}
	else {
		ResetFPGA(fdFPGA);
		printf( "Reset FPGA\n");
	}
	//-------------------------------------------------------------
	
	
	//hmlee - no need to keep the old one
	//hmlee - somehow good to keep old one but old one mess with ReadNWriteLOG() function
	unlink(NameRAMLogFile);
	
	//Open RAM LOG Driver --------------------------------------------------
	//printf("Open Log File in the RAM\n");
	//	
	////fdRLOG = open( NameRAMLogFile, O_RDWR | O_APPEND | O_CREAT);
	//fdRLOG = open( NameRAMLogFile, O_RDWR | O_CREAT | O_NONBLOCK );
	//if ( fdRLOG < 0 )
	//{
	//	printf( "Open Error Log File in the RAM...:%s\n", NameRAMLogFile );
	//	exit(-1);
	//}
	//--------------------------------------------------------------

/*
	//Open TOD Port Driver ---------------------------------------
	printf("Open TOD COM Port Driver\n");

	fdTOD = open( name_Port_TOD, O_RDWR | O_NOCTTY | O_NONBLOCK );
	if(fdTOD<0){
		printf( "ttyS3 Open Error ...:%d\n",fdTOD);
		exit(-1);
	}
	set_tty( fdTOD, B9600, 0 );
	//-------------------------------------------------------------
*/
	

	//Open Rb-SRO-100 Port Driver ---------------------------------------
	printf("Open Rb COM Port Driver\n");

	fdRbSRO = open( name_Port_RbSRO, O_RDWR | O_NOCTTY | O_NONBLOCK );
	if(fdRbSRO<0){
		printf( "ttyS2 Open Error ...:%d\n",fdRbSRO);
		exit(-1);
	}
	set_tty( fdRbSRO, B9600, 0 );
	//-------------------------------------------------------------

	
	//Open GPS Receiver Serial Port Driver ---------------------------------------
	printf("Open EB COM Port Driver\n");

	fdEB = open( name_Port_EB, O_RDWR | O_NOCTTY | O_NONBLOCK );
	if(fdEB<0){
		printf( "ttyS3 Open Error ...:%d\n",fdEB);
		exit(-1);
	}
	set_tty( fdEB, B115200, 1 );
	//-------------------------------------------------------------

	//Open GPS Receiver Serial Port Driver ---------------------------------------
	printf("Open EB2 COM Port Driver\n");

	fdEB2 = open( name_Port_EB2, O_RDWR | O_NOCTTY | O_NONBLOCK );
	if(fdEB2<0){
		printf( "ttyS1 Open Error ...:%d\n",fdEB2);
		exit(-1);
	}

	set_tty( fdEB2, B115200, 2 );
	//-------------------------------------------------------------
	/*
	//Open GPS Receiver Serial Port Driver ---------------------------------------
	printf("Open TEST COM Port Driver\n");

	fdtest = open( name_Port_test, O_RDWR | O_NOCTTY | O_NONBLOCK );
	if(fdtest<0){
		printf( "ttyS4 Open Error ...:%d\n",fdtest);
		exit(-1);
	}

	set_tty( fdtest, B115200, 2 );
	//-------------------------------------------------------------
*/


	/*
	//Open DUAL Serial Port Driver -------------------------------------------
	printf("Open DUAL COM Port Driver\n");

	fdDUAL = open( name_Port_DUAL, O_RDWR | O_NOCTTY | O_NONBLOCK );
	if(fdDUAL<0){
		printf( "ttyS1 Open Error ...:%d\n",fdDUAL);
		exit(-1);
	}
	set_tty( fdDUAL, B57600, 2 );
	//--------------------------------------------------------------
	*/
	
	//hmlee - need for timer interrupt alarm or "alarm" function
	memset(&sa, 0, sizeof (sa));
	sa.sa_handler = sig_handler_alarm;
	sigaction(SIGALRM, &sa, NULL);
	
	//hmlee - if program gets "kill" signal 
	//signal(SIGINT, sig_handler_exit);
	signal(SIGQUIT, sig_handler_exit);
	signal(SIGTERM, sig_handler_exit);
	signal(SIGCHLD, SIG_IGN);

	printf( "\n" );

	if( 1 ){
		
		if(!debug_test_run){
			if(daemon(0, 1) == -1){
				printf("deamon error %d, %s\n", errno, strerror(errno));
				exit(-1);
			}
		}
		
		//hmlee - no more alarm interrupt
		signal(SIGALRM, SIG_IGN);

		//hmlee - setup SIGIO interrupt
		memset(&sa, 0, sizeof (sa));
		sa.sa_sigaction = sig_handler_fasync;
		sigemptyset(&sa.sa_mask);
		sa.sa_flags = SA_SIGINFO;
		sigaction(SIGIO, &sa, 0);

		//hmlee - some more setup to get SIGIO signal
		if((fcntl(fdFPGA, F_SETOWN, getpid())) < 0){
		    printf("F_SETOWN fails \n");
		    exit(-1);
		}

		//hmlee - some more setup to get SIGIO signal
		flags = fcntl(fdFPGA, F_GETFL);
		if((fcntl(fdFPGA, F_SETFL, flags | FASYNC)) < 0){
			printf("F_SETFL fails \n");
		   	exit(-1);
		}
		
		memset(&sa, 0, sizeof (sa));
		sa.sa_sigaction = sig_handler_int;
		sigemptyset(&sa.sa_mask);
		sa.sa_flags = SA_RESTART;
		sigaction(SIGINT, &sa, 0);

		memset(&schedp, 0, sizeof(schedp));
		//schedp.sched_priority = sched_get_priority_max(SCHED_RR);	
		//schedp.sched_priority = sched_get_priority_max(SCHED_FIFO);
		schedp.sched_priority = 99;
		//if (sched_setscheduler(0, SCHED_RR, &schedp)!=0){
		if (sched_setscheduler(0, SCHED_FIFO, &schedp)!=0){
			LogItString(LOG_CATA1_NORM, LOG_CATA2_FAIL, "sched_setscheduler max");
		}
		
		//memset(&schedp, 0, sizeof(schedp));
		////schedp.sched_priority = sched_get_priority_max(SCHED_RR);	
		////schedp.sched_priority = sched_get_priority_max(SCHED_FIFO);
		//schedp.sched_priority = 0;
		////if (sched_setscheduler(0, SCHED_RR, &schedp)!=0){
		//if (sched_setscheduler(0, SCHED_OTHER, &schedp)!=0){
		//	LogItString("sched_setscheduler max failed");
		//}

		if (mlockall(MCL_CURRENT | MCL_FUTURE) !=0){
			LogItString(LOG_CATA1_NORM, LOG_CATA2_FAIL, "mlockall");
		}

		//fwup_fork_init();
		//inv_fork_init();

		_main(fdFPGA);  //RCGD-M _main()
	
		//hmlee - why on earth "Init_DUAL" should be here??
		//Init_DUAL();
	}

	printf( "\n" );

	exit(0);
}





